#ifndef __OPENGL_WINDOW_HH__
#define __OPENGL_WINDOW_HH__

#include <opengl/texture.h>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <string>
#include <map>

namespace opengl
{

//! @brief 使用 glfw 实现 opengl 窗口
class Window
{
public:
    //! @brief 构造与析构
    Window(int width, int height, std::string title, const glm::vec4& backColor) noexcept;
    virtual ~Window() noexcept;

    //! @brief 渲染循环
    void show();

protected:
    //! @brief 绑定当前窗口到上下文
    void bind();

    //! @brief 释放资源
    void free();

    //! @brief 渲染函数
    virtual void render() = 0;

    //! @brief 程序输入控制
    virtual void processInput() = 0;

    //! @brief 回调函数
    virtual void framebufferSizeCallback(GLFWwindow* window, int width, int height);
    virtual void cursorPosCallback(GLFWwindow* window, double xpos, double ypos);
    virtual void scrollCallback(GLFWwindow* window, double xoffset, double yoffset);
    virtual void mouseButtonCallback(GLFWwindow *window, int button, int action, int mods);
    virtual void keyboardCallback(GLFWwindow* window, int key, int scancode, int action, int mods);

    //! @brief 回收子类窗口资源
    virtual void freeResources() = 0;

private:
    //! @brief 初始化 OpenGL 窗口
    void initWindow();
    //! @brief 开启 OpenGL 功能
    void enbaleFunction() noexcept;
    //! @brief 注册回调函数
    void registerCallBack() noexcept;

    // 回调函数接口，直接根据当前 window 对象执行其回调函数处理
    static void framebufferSizeCallbackInterface(GLFWwindow* window, int width, int height);
    static void cursorPosCallbackInterface(GLFWwindow* window, double xpos, double ypos);
    static void scrollCallbackInterface(GLFWwindow* window, double xoffset, double yoffset);
    static void mouseButtonCallbackInterface(GLFWwindow *window, int button, int action, int mods);
    static void keyboardCallbackInterface(GLFWwindow* window, int key, int scancode, int action, int mods);

public:
    //! @brief 初始化 glfw
    static void init();
    //! @brief 注销 glfw
    static void terminate();

protected:
    int _width;
    int _height;
    std::string _title;
    glm::vec4 _backColor;
    GLFWwindow* _window;
};

}

#endif